﻿using Fake_Shop_WebApi.Dtos;
using Fake_Shop_WebApi.Models;
using Fake_Shop_WebApi.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.JsonWebTokens;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;

namespace Fake_Shop_WebApi.Controllers
{
    [ApiController]
    [Route("auth")]
    public class AuthenticateControllers:ControllerBase
    {
        private readonly IConfiguration _configuration;
        private readonly UserManager<ApplicationUser> _userManager;
        private readonly SignInManager<ApplicationUser> _signInManager;
        private readonly ITouristRouteRepository _touristRouteRepository;

        public AuthenticateControllers(IConfiguration configuration,
            UserManager<ApplicationUser> userManager,
            SignInManager<ApplicationUser> signInManager,
            ITouristRouteRepository touristRouteRepository
            )
        {
            _configuration = configuration;
            _userManager = userManager;
            _signInManager = signInManager;
            _touristRouteRepository = touristRouteRepository;
        }
        [AllowAnonymous]
        [HttpPost]
        [Route("login")]
        public async Task<IActionResult> login([FromBody]loginDto loginDto)
        {
            //1.验证用户账号密码
            var loginRes = await _signInManager.PasswordSignInAsync(
                loginDto.Email,
                loginDto.Password,
                false,//关闭输入错误多次锁定账号
                false
                );
            //根据用户的Email获取用户数据
            var user = await _userManager.FindByNameAsync(loginDto.Email);
            //2.创建JWT
            //JWT分为三个部分,分别保存不同的信息
            //header   头部
            var signingAlgorithm = SecurityAlgorithms.HmacSha256;//摘要安全加密算法
             //payload  载荷
            /*
            iss: jwt签发者
             sub: jwt所面向的用户
             aud: 接收jwt的一方
             exp: jwt的过期时间，这个过期时间必须要大于签发时间
             nbf: 定义在什么时间之前，该jwt都是不可用的.
             iat: jwt的签发时间
             jti: jwt的唯一身份标识，主要用来作为一次性token,从而回避重放攻击
             */
            var claims = new List<Claim>
            /*   Claim
             *   资源的所有权
             *   表诉用户的身份 、说明用户的角色、表示用户所具有的权限
             *   最小不可分割单位、使用的灵活度相当高
             *   
             *   验证与授权完全分开
             *   使用的是基于Claims的身份认证体系
             *   JWT只是Claim的其中一种应用而已
             */

            {
                 //sub 指定面向的用户
                 new Claim(Microsoft.IdentityModel.JsonWebTokens.JwtRegisteredClaimNames.Sub,user.Id),
                 //把Admin设置为管理员权限
                 new Claim(ClaimTypes.Role,"Admin"),
             };
            //获取用户角色
            var RoleNames = await _userManager.GetRolesAsync(user);
            foreach (var roleName in RoleNames)
            {
                var RoleClaim = new Claim(ClaimTypes.Role, roleName);
                claims.Add(RoleClaim);
            }
            //signiture  签名
            var secretByte = Encoding.UTF8.GetBytes(_configuration["Authentication:SecretKey"]);
            var signingKey = new SymmetricSecurityKey(secretByte);//非对称算法加密私钥
            var signingCredentials = new SigningCredentials(signingKey, signingAlgorithm);//验证加密后的私钥，第一个是签名的，第二个是头部的

            var token = new JwtSecurityToken(
                issuer:_configuration["Authentication:Issuer"],//签发人
                audience:_configuration["Authentication:Audience"],//受众
                claims,
                notBefore:DateTime.UtcNow,//生效时间
                expires:DateTime.UtcNow.AddDays(1),//失效时间
                signingCredentials
                );
            //获取token
            var tokenStr = new JwtSecurityTokenHandler().WriteToken(token);
            //3.return  200 OK
            return Ok(tokenStr);


        }

        [AllowAnonymous]
        [HttpPost("register")]
        public async Task<IActionResult> Register([FromBody]RegisterDto registerDto)
        {
            var user = new ApplicationUser()
            {
                UserName = registerDto.Email,
                Email = registerDto.Email,
                
            };
            //加密密码，保存用户
            var result = await _userManager.CreateAsync(user,registerDto.PassWord);
            if (!result.Succeeded)
            {
                return BadRequest();//返回404
            }
            //初始化购物车
            ShoppingCart shoppingCart = new ShoppingCart()
            {
                Id = Guid.NewGuid(),
                UserId = user.Id,
            };
            await _touristRouteRepository.CreateShoppingCartAsync(shoppingCart);
            await _touristRouteRepository.SaveAsync();
            return Ok("注册成功");
        }
    }
}
